
#include "RtBase.h"
#include "RtTimerWrapper.h"
#include "RtThreadManager.h"
#include "RtThreadInterface.h"
#include "RtTimeValue.h"


//////////////////////////////////////////////////////////////////////
// class CRtTimerWrapperSink
//////////////////////////////////////////////////////////////////////

/*
CRtTimerWrapperSink::~CRtTimerWrapperSink()
{
}
*/


//////////////////////////////////////////////////////////////////////
// class CRtTimerWrapper
//////////////////////////////////////////////////////////////////////

CRtTimerWrapper::CRtTimerWrapper()
	: m_bScheduled(FALSE)
	, m_pTimerQueue(NULL)
	, m_count(0)
{
	// Don't get timer queue in the contruct function.
	// get timer queue in the Schedule() function.
}

CRtTimerWrapper::~CRtTimerWrapper()
{
	Cancel();
}

RtResult CRtTimerWrapper::Schedule(CRtTimerWrapperSink *aSink, const CRtTimeValue &aInterval, DWORD aCount)
{
// 	RT_INFO_TRACE_THIS("CRtTimerWrapper::Schedule, sink="<<aSink<<" m_bScheduled="<<m_bScheduled);
	//RT_ASSERTE_RETURN(!m_bScheduled, RT_ERROR_WRONG_STATUS);

	RtResult rv = RT_ERROR_NULL_POINTER;
	RT_ASSERTE(aSink);
	
	if (!m_pTimerQueue) {
		CRtThread* pThread = 
			CRtThreadManager::Instance()->GetThread(CRtThreadManager::TT_CURRENT);
		if (pThread)
			m_pTimerQueue = pThread->GetTimerQueue();

		if (!m_pTimerQueue) {
			RT_WARNING_TRACE_THIS("CRtTimerWrapper::Schedule, this thread doesn't suppport TimerQueue! sink="<<aSink);
			return rv;
		}
	}
	
	if(m_bScheduled)
		Cancel();

	m_bScheduled = TRUE;
	m_count = aCount;
	rv = m_pTimerQueue->ScheduleTimer(this, aSink, aInterval, aCount);
	return rv;
}

RtResult CRtTimerWrapper::Cancel()
{
// 	RT_INFO_TRACE_THIS("CRtTimerWrapper::Cancel, m_bScheduled="<<m_bScheduled);
	if (!m_bScheduled)
		return RT_OK;
	m_bScheduled = FALSE;
	m_count = 0;

	RtResult rv = RT_ERROR_NULL_POINTER;
	if (m_pTimerQueue)
	{
		rv = m_pTimerQueue->CancelTimer(this);
		//m_pTimerQueue = NULL;
	}
	return rv;
}

void CRtTimerWrapper::OnTimeout(const CRtTimeValue &, LPVOID aArg)
{
	RT_ASSERTE(m_bScheduled);
	
	if (m_count>0)
	{
		--m_count;
		if (m_count==0)
			m_bScheduled = FALSE;
	}
	CRtTimerWrapperSink *pSink = static_cast<CRtTimerWrapperSink *>(aArg);
	RT_ASSERTE(pSink);
#ifdef RT_WIN32
	try
	{
#endif
	if (pSink)
		pSink->OnTimer(this);
#ifdef RT_WIN32
	}
	catch (...)
	{
		RT_ERROR_TRACE_THIS("CRtTimerWrapper::OnTimeout, catch exception! sink="<<pSink);
	}
#endif
}
